﻿namespace MEF_Test
{
    using System;
    using System.ComponentModel;
    using System.Windows.Controls;

    using MEF_Test.Bricks;
    using MEF_Test.Bricks.Mediator;

    using Microsoft.Practices.Prism.Regions;

    /// <summary>
    /// The View Model responsible for the navigation between the different views.
    /// </summary>
    public class MainWindowViewModel : INotifyPropertyChanged
    {
        #region Constants and Fields

        /// <summary>
        /// The name of the <see cref="CurrentView"/> property
        /// </summary>
        private static readonly string _currentViewPropertyName = PropertyHelper.MemberName<MainWindowViewModel>(o => o.CurrentView);

        /// <summary>
        /// The name of the <see cref="CurrentViewUri"/> property.
        /// </summary>
        private static readonly string _currentViewUriPropertyName = PropertyHelper.MemberName<MainWindowViewModel>(o => o.CurrentViewUri);

        /// <summary>
        /// The backing field for the <see cref="CurrentView"/> property.
        /// </summary>
        private Page _currentView;

        /// <summary>
        /// The backing field for the <see cref="CurrentViewUri"/>
        /// </summary>
        private Uri _currentViewUri;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="MainWindowViewModel"/> class.
        /// </summary>
        /// <param name="defaultViewUri">The URI of the default view.</param>
        /// <param name="regionManager">The region manager.</param>
        public MainWindowViewModel(Uri defaultViewUri, IRegionManager regionManager)
        {
            if (defaultViewUri == null)
            {
                throw new ArgumentNullException("defaultViewUri");
            }

            if (regionManager == null)
            {
                throw new ArgumentNullException("regionManager");
            }

            var region = regionManager.Regions["LocalControls"];
            region.Activate(region.GetView("NavigationView"));

            // Every time the ChangeMainViewMediation "event" is published, retrieve the view uri or
            // the page instance and set the data-bound property with it !
            Mediator<ChangeMainViewMediation>.Register(m =>
                {
                    // either we get an instance of a page, or the URI :
                    // in either case, as the properties are bound to
                    // the frame element, setting it will issue a navigation request.
                    if (m.View != null)
                    {
                        CurrentView = m.View;
                    }
                    else
                    {
                        CurrentViewUri = m.ViewUri;
                    }
                });

            // ... and as we need to be consistant, we'll publish the default uri right away.
            // I prefer doing so instead of setting the property directly, even if there is a little overhead, for the sake of maintainability.
            Mediator<ChangeMainViewMediation>.Publish(new ChangeMainViewMediation { ViewUri = defaultViewUri });
        }

        #endregion

        #region Events

        /// <summary>
        /// Occurs when a property value changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the current view.
        /// </summary>
        /// <value>The current view.</value>
        public Page CurrentView
        {
            get
            {
                return _currentView;
            }

            set
            {
                if (_currentView != value)
                {
                    _currentView = value;
                    if (PropertyChanged != null)
                    {                        
                        PropertyChanged(this, new PropertyChangedEventArgs(_currentViewPropertyName));
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the current view URI.
        /// </summary>
        /// <value>The current view URI.</value>
        public Uri CurrentViewUri
        {
            get
            {
                return _currentViewUri;
            }

            set
            {
                if (_currentViewUri != value)
                {
                    _currentViewUri = value;
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(_currentViewUriPropertyName));
                    }
                }
            }
        }

        #endregion
    }
}
